package com.itdct.onflow.system.common.processor

import com.itdct.onflow.core.annotation.TableDescription
import com.itdct.onflow.core.config.OnflowConfig
import com.itdct.onflow.core.entity.IdEntity
import com.itdct.onflow.core.extend.logInfo
import com.itdct.onflow.generator.base.BaseTemplate
import com.itdct.onflow.generator.config.GeneratorConfig
import com.itdct.onflow.generator.constant.GroupEnum
import com.itdct.onflow.generator.core.CodeGenerator
import com.itdct.onflow.generator.core.EntityAnalyse
import com.itdct.onflow.generator.model.ClassModel
import com.itdct.onflow.generator.template.*
import com.itdct.onflow.generator.template.web.*
import jakarta.annotation.PostConstruct
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.ApplicationContext
import org.springframework.stereotype.Component


/**
 * @author Zhouwx
 * @date 2025/8/18 10:53:40
 * @version 1.0
 * @description
 */
@Component
class TableDescriptionProcessor(
    val applicationContext: ApplicationContext,
    val onflowConfig: OnflowConfig,
    @Value("\${spring.datasource.url:127.0.0.1/unknown}")
    val url: String,
    @Value("\${spring.datasource.username:root}")
    val username: String,
    @Value("\${spring.datasource.password:}")
    val password: String
) {

    @PostConstruct // 容器启动完成后执行
    fun processAnnotatedClasses() {
        val onflowGenerateConfig = onflowConfig.generate
        if (!onflowGenerateConfig.enable) {
            logInfo("自动生成器未开启")
            return
        }

        // 获取所有带@TableDescription注解的Bean实例
        val beans = applicationContext.getBeansWithAnnotation(TableDescription::class.java)
        val generatorConfig = GeneratorConfig()
        generatorConfig.sessionVersion = onflowGenerateConfig.sessionVersion
        generatorConfig.authorName = onflowGenerateConfig.authorName
        generatorConfig.groupModulePath[GroupEnum.BACKEND] = onflowGenerateConfig.backendPath
        generatorConfig.groupModulePath[GroupEnum.MAPPER_XML] = onflowGenerateConfig.backendPath
        generatorConfig.groupModulePath[GroupEnum.FRONTEND] = onflowGenerateConfig.frontendPath
//        generatorConfig.syncMenu = onflowGenerateConfig.syncMenu
        generatorConfig.groupId = onflowGenerateConfig.groupId
        generatorConfig.syncTable = onflowGenerateConfig.syncTable

        var ip = "127.0.0.1"
        var port = 3306
        var startIndex = url.indexOf("//") + 2
        var endIndex = url.indexOf("/", startIndex + 1)
        val ipPort = url.substring(startIndex, endIndex)
        if (ipPort.contains(":")) {
            val split = ipPort.split(":")
            ip = split[0]
            port = split[1].toInt()
        } else {
            ip = ipPort
        }
        var databaseName = ""
        endIndex = url.indexOf("?")
        if (endIndex == -1) {
            // INFO: Zhouwx: 2025/8/19 不存在问号，说明最后的就是数据库名称
            databaseName = url.substring(url.lastIndexOf("/") + 1)
        } else {
            databaseName = url.substring(url.lastIndexOf("/", endIndex) + 1, endIndex)
        }
        logInfo("数据库信息: ip: $ip, port: $port, databaseName: $databaseName")
        generatorConfig.databaseIp = ip
        generatorConfig.databasePort = port.toString()
        generatorConfig.databaseName = databaseName
        generatorConfig.databaseUserName = username
        generatorConfig.databasePassword = password

        val templateClassList = ArrayList<Class<out BaseTemplate>>()
        templateClassList.add(EditQoTemplate::class.java)
        templateClassList.add(SearchQoTemplate::class.java)
        templateClassList.add(ListVoTemplate::class.java)
        templateClassList.add(DetailVoTemplate::class.java)
        templateClassList.add(MapperJavaTemplate::class.java)
        templateClassList.add(MapperXmlTemplate::class.java)
        templateClassList.add(ManagerTemplate::class.java)
        templateClassList.add(ServiceTemplate::class.java)
        templateClassList.add(ControllerTemplate::class.java)

        if (onflowGenerateConfig.syncFrontend) {
            templateClassList.add(VueTypesTemplate::class.java)
            templateClassList.add(VueIndexTemplate::class.java)
            templateClassList.add(VueEditTemplate::class.java)
            templateClassList.add(VuePageTemplate::class.java)
            templateClassList.add(VueWriteTemplate::class.java)
        }

        val codeGenerator = CodeGenerator(generatorConfig, templateClassList)

        val filteredClasses = beans.map { it.value }
            .filter { bean ->
                val clazz = bean.javaClass
                val tableDescription = clazz.getAnnotation(TableDescription::class.java)

                // 过滤条件检查
                if (tableDescription == null) {
                    logInfo("忽略Bean: ${bean.javaClass.simpleName}")
                    return@filter false
                }

                if (!tableDescription.autoSync) {
                    logInfo("忽略Bean: ${bean.javaClass.simpleName}")
                    return@filter false
                }

                if (!IdEntity::class.java.isAssignableFrom(clazz)) {
                    logInfo("忽略Bean: ${bean.javaClass.simpleName}")
                    return@filter false
                }
                true
            }
            .map { it.javaClass as Class<IdEntity> }

        val classModels = ArrayList<ClassModel>()
        for (filteredClass in filteredClasses) {
            val entityAnalyse = EntityAnalyse<IdEntity>(generatorConfig)
            val classModel = entityAnalyse.analyseClass(filteredClass)
            classModels.add(classModel)
        }

        if (!onflowGenerateConfig.enable) {
            logInfo("自动生成器未开启")
            return
        }

        codeGenerator.generates(*classModels.toTypedArray())
    }
}